﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
#if !NET20
using System.Dynamic;
using System.IO;
#endif
using System.Reflection;
using static Apewer.NumberUtility;
using static Apewer.RuntimeUtility;

namespace Apewer
{

    /// <summary>Json。</summary>
    [Serializable]
    public sealed class Json
#if !NET20
        : DynamicObject
#endif
    {

        #region 配置。

        [NonSerialized]
        private static bool _throw = false;

        [NonSerialized]
        private static bool _recursively = true;

        [NonSerialized]
        private static bool _forceall = true;

        /// <summary>允许抛出 Exception，默认为不允许。</summary>
        public static bool AllowException { get { return _throw; } set { _throw = value; } }

        /// <summary>当存在递归引用时候包含递归项。指定为 True 时递归项为 Null 值，指定为 False 时不包含递归项。默认值：False。</summary>
        public static bool AllowRecursively { get { return _recursively; } set { _recursively = value; } }

        /// <summary>将所有类型视为拥有 <see cref="SerializableAttribute" /> 特性。</summary>
        /// <remarks>默认值：FALSE。</remarks>
        public static bool ForceAll { get => _forceall; set => _forceall = value; }

        #endregion

        #region 消息

        private const string ValueIsNotSupported = "指定的值类型不受支持";
        private const string IsNotJsonObject = "当前实例不是 Json 对象。";
        private const string IsNotJsonArray = "当前实例不是 Json 数组。";
        private const string InvalidIndex = "未指定有效的索引。";
        private const string IndexLessZero = "指定的索引小于 0，无效。";
        private const string IndexGraterMax = "指定的索引超出了最大值，无效。";
        private const string IndexGraterCount = "指定的索引超出了数量，无效。";

        #endregion

        #region JToken

        [NonSerialized]
        private JToken _jtoken = null;

        [NonSerialized]
        private JArray _jarray = null;

        [NonSerialized]
        private JObject _jobject = null;

        [NonSerialized]
        private JProperty _jproperty = null;

        [NonSerialized]
        private JValue _jvalue = null;

        static JToken ToJToken(object value)
        {
            if (value == null) return new JValue(null, JTokenType.Null);

            var type = value.GetType();
            if (RuntimeUtility.IsNullableType(type)) value = RuntimeUtility.GetNullableValue(value);

            if (value == null) return new JValue(null, JTokenType.Null);
            if (value is Json json) return json?._jtoken ?? new JValue(null, JTokenType.Null);
            if (value is DateTime dt) return new JValue(SerializeDateTime(dt));

            if (value is string) return new JValue(value);
            if (value is bool) return new JValue(value);

            if (value is byte) return new JValue(value);
            if (value is sbyte) return new JValue(value);
            if (value is short) return new JValue(value);
            if (value is ushort) return new JValue(value);
            if (value is int) return new JValue(value);
            if (value is uint) return new JValue(value);
            if (value is long) return new JValue(value);
            if (value is ulong uint64) return (uint64 > int.MaxValue) ? new JValue(uint64.ToString()) : new JValue(Convert.ToInt64(uint64));

            if (value is float) return new JValue(value);
            if (value is double) return new JValue(value);
            if (value is decimal) return new JValue(value);

            var from = From(value);
            if (from != null) return from._jtoken;
            throw new ArgumentException(ValueIsNotSupported);
        }

        static object ParseJToken(JToken jtoken)
        {
            if (jtoken == null) return null;
            if (jtoken is JValue jvalue) return jvalue.Value;
            if (jtoken is JObject) return new Json(jtoken);
            if (jtoken is JArray) return new Json(jtoken);
            if (jtoken is JProperty jproperty)
            {
                var value = jproperty.Value;
                if (value == null) return null;
                return ParseJToken(value);
            }
            throw new InvalidOperationException($"Json 类型 {jtoken.Type} 不支持解析。");
        }

        #endregion

        #region 构造。

        #region Reset

        /// <summary>重置当前对象为空。</summary>
        public void Reset()
        {
            Construct();
        }

        /// <summary>使用指定的文本重置当前对象。</summary>
        public bool Reset(string json)
        {
            Construct();
            if (json == null)
            {
                if (AllowException) throw new ArgumentNullException("json", "参数无效。");
                return false;
            }
            var parsed = From(json);
            if (parsed == null) return false;
            Construct(parsed._jtoken);
            return true;
        }

        /// <summary>使用指定的对象重置当前对象。</summary>
        /// <exception cref="System.Exception"></exception>
        /// <exception cref="System.ArgumentNullException"></exception>
        public bool Reset(Json json)
        {
            Construct();
            if (json == null)
            {
                if (AllowException) throw new ArgumentNullException("json", "参数无效。");
                return false;
            }
            var parsed = From(json.ToString());
            if (parsed == null) return false;
            Construct(parsed._jtoken);
            return true;
        }

        /// <summary>使用指定的字典对象重置当前对象。</summary>
        /// <exception cref="System.Exception"></exception>
        /// <exception cref="System.ArgumentNullException"></exception>
        public bool Reset(Dictionary<string, string> dictionary)
        {
            Construct();
            if (dictionary == null)
            {
                if (AllowException) throw new ArgumentNullException("dictionary", "参数无效。");
                return false;
            }
            var json = NewObject();
            foreach (var item in dictionary) json[item.Key] = item.Value;
            Construct(json._jtoken);
            return true;
        }

        /// <summary>使用指定的文本字典对象重置当前对象。</summary>
        /// <exception cref="System.Exception"></exception>
        /// <exception cref="System.ArgumentNullException"></exception>
        public bool Reset(TextSet dictionary)
        {
            Construct();
            if (dictionary == null)
            {
                if (AllowException) throw new ArgumentNullException("dictionary", "参数无效。");
                return false;
            }
            return Reset(dictionary.Origin);
        }

        /// <summary>使用指定的文本字典对象重置当前对象。</summary>
        /// <exception cref="System.Exception"></exception>
        /// <exception cref="System.ArgumentNullException"></exception>
        public bool Reset(ObjectSet<string> dictionary)
        {
            Construct();
            if (dictionary == null)
            {
                if (AllowException) throw new ArgumentNullException("dictionary", "参数无效。");
                return false;
            }
            return Reset(dictionary.Origin);
        }

        #endregion

        private void Construct(JToken jtoken = null)
        {
            _jtoken = jtoken;
            _jarray = null;
            _jobject = null;
            _jproperty = null;
            _jvalue = null;
            if (_jtoken != null)
            {
                if (_jtoken is JArray) _jarray = (JArray)_jtoken;
                if (_jtoken is JObject) _jobject = (JObject)_jtoken;
                if (_jtoken is JProperty) _jproperty = (JProperty)_jtoken;
                if (_jtoken is JValue) _jvalue = (JValue)_jtoken;
            }
        }

        private Json(JToken jtoken)
        {
            Construct(jtoken);
        }

        /// <summary>创建 Json Object 实例。</summary>
        public Json()
        {
            Construct(new JObject());
        }

        #endregion

        #region 属性。

        /// <summary>用于兼容 SimpleJson 的操作。</summary>
        public string this[string name] { get => GetProperty(name)?.ToString() ?? ""; set => SetProperty(name, value ?? ""); }

        /// <summary>获取或设置数组的元素。</summary>
        public object this[int index] { get => GetItem(index); set => SetItem(index, value); }

        private JTokenType TokenType
        {
            get
            {
                if (_jtoken == null) return JTokenType.None;
                else return _jtoken.Type;
                //if (_jtoken == null) return 0;
                //switch (_jtoken.Type)
                //{
                //    case JTokenType.None: return 0;
                //    case JTokenType.Object: return 1;
                //    case JTokenType.Array: return 2;
                //    case JTokenType.Constructor: return 3;
                //    case JTokenType.Property: return 4;
                //    case JTokenType.Comment: return 5;
                //    case JTokenType.Integer: return 6;
                //    case JTokenType.Float: return 7;
                //    case JTokenType.String: return 8;
                //    case JTokenType.Boolean: return 9;
                //    case JTokenType.Null: return 10;
                //    case JTokenType.Undefined: return 11;
                //    case JTokenType.Date: return 12;
                //    case JTokenType.Raw: return 13;
                //    case JTokenType.Bytes: return 14;
                //    case JTokenType.Guid: return 15;
                //    case JTokenType.Uri: return 16;
                //    case JTokenType.TimeSpan: return 17;
                //    default: return 0;
                //}
            }
        }

        /// <summary>
        /// <para>获取当前实例的类型。可能的类型：</para>
        /// <para>None Object Array Constructor Property Comment Integer Float String</para>
        /// <para>Boolean Null Undefined Date Raw Bytes Guid Uri TimeSpan</para>
        /// </summary>
        public string Type { get { return TokenType.ToString(); } }

        /// <summary>实例有效。</summary>
        public bool Available { get { return _jtoken != null && TokenType != JTokenType.None; } }

        /// <summary>获取当前实例的值，当为 Json 格式时缩进。</summary>
        public string Lucid { get { return ToString(true); } }

        /// <summary>获取当前实例的值，当为 Json 格式时不缩进。</summary>
        public string Text { get { return ToString(false); } }

        /// <summary>当前实例类型为 Property 时，获取名称。</summary>
        public string Name
        {
            get { return _jproperty == null ? null : _jproperty.Name; }
        }

        /// <summary>获取值。</summary>
        public object Value
        {
            get
            {
                if (_jvalue != null)
                {
                    if (_jvalue.Value == null) return null;
                    if (_jvalue.Value is JValue jvalue) return jvalue.Value;
                    if (_jvalue.Value is JToken jtoken) return new Json(jtoken);
                    else return _jvalue.Value;
                }
                if (_jproperty != null)
                {
                    if (_jproperty.Value == null) return null;
                    if (_jproperty.Value is JValue jvalue) return jvalue.Value;
                    if (_jproperty.Value is JToken jtoken) return new Json(jtoken);
                    else return _jproperty.Value;
                }
                return null;
            }
        }

        /// <summary>实例无效。</summary>
        public bool IsNull { get { return _jtoken == null; } }

        #endregion

        #region Private Get

        private Json[] PrivateGetProperties { get { return GetProperties(); } }

        private Json[] PrivateGetValues { get { return GetValues(); } }

        private Json[] PrivateGetObjects { get { return GetObjects(); } }

        private Json[] PrivateGetItems { get { return GetItems(); } }

        #endregion

        #region Object : Get/Set

        /// <summary>获取所有类型为 Property 的子项。</summary>
        public Json[] GetProperties()
        {
            var ab = new ArrayBuilder<Json>();
            if (_jobject != null)
            {
                var children = _jobject.Children();
                foreach (var child in children)
                {
                    var json = new Json(child);
                    ab.Add(json);
                }
            }
            return ab.Export();
        }

        /// <summary>当前实例类型为 Object 时搜索属性，失败时返回 Null。</summary>
        /// <param name="name">将要搜索的属性名称，不可为 Null。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public Json GetProperty(string name)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return null;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }

            var children = _jtoken.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    var json = new Json(child.Value);
                    return json;
                }
            }
            return null;
        }

        /// <summary>当前实例类型为 Object 时添加属性，值为 Null，已存在的属性将被替换。</summary>
        /// <param name="name">将要添加的属性名称，不可为 Null。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(string name)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return false;
            }

            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            _jobject.Add(name, null);
            return true;
        }

        /// <summary>当前实例类型为 Object 时添加属性，已存在的属性将被替换。</summary>
        /// <param name="property">将要添加的属性。</param>
        /// <exception cref="System.ArgumentException"></exception>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(Json property)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (property == null)
            {
                if (_throw) throw new ArgumentNullException("property", "参数无效。");
                return false;
            }

            if (property._jproperty == null || property.TokenType != JTokenType.Property)
            {
                if (_throw) throw new ArgumentException("property", "将要设置的属性无效。");
                return false;
            }

            var name = property._jproperty.Name;
            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            _jobject.Add(name, property._jtoken);
            return true;
        }

        /// <summary>当前实例类型为 Object 时添加属性，已存在的属性将被替换。</summary>
        /// <param name="name">将要添加的属性名称，不可为 Null。</param>
        /// <param name="value">将要添加的属性值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(string name, bool value)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return false;
            }

            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            _jobject.Add(name, value);
            return true;
        }

        /// <summary>当前实例类型为 Object 时添加属性，已存在的属性将被替换。</summary>
        /// <param name="name">将要添加的属性名称，不可为 Null。</param>
        /// <param name="value">将要添加的属性值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(string name, string value)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return false;
            }

            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            _jobject.Add(name, value);
            return true;
        }

        /// <summary>当前实例类型为 Object 时添加属性，已存在的属性将被替换。</summary>
        /// <param name="name">将要添加的属性名称，不可为 Null。</param>
        /// <param name="value">将要添加的属性值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(string name, int value)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return false;
            }

            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            _jobject.Add(name, value);
            return true;
        }

        /// <summary>当前实例类型为 Object 时添加属性，已存在的属性将被替换。</summary>
        /// <param name="name">将要添加的属性名称，不可为 Null。</param>
        /// <param name="value">将要添加的属性值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(string name, long value)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return false;
            }

            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            _jobject.Add(name, value);
            return true;
        }

        /// <summary>当前实例类型为 Object 时添加属性，已存在的属性将被替换。</summary>
        /// <param name="name">将要添加的属性名称，不可为 Null。</param>
        /// <param name="value">将要添加的属性值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(string name, float value)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return false;
            }

            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            _jobject.Add(name, value);
            return true;
        }

        /// <summary>当前实例类型为 Object 时添加属性，已存在的属性将被替换。</summary>
        /// <param name="name">将要添加的属性名称，不可为 Null。</param>
        /// <param name="value">将要添加的属性值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(string name, double value)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return false;
            }

            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            _jobject.Add(name, value);
            return true;
        }

        /// <summary>当前实例类型为 Object 时添加属性，已存在的属性将被替换。</summary>
        /// <param name="name">将要添加的属性名称，不可为 Null。</param>
        /// <param name="value">将要添加的属性值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(string name, decimal value)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return false;
            }

            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            _jobject.Add(name, value);
            return true;
        }

        /// <summary>当前实例类型为 Object 时添加属性，已存在的属性将被替换。</summary>
        /// <param name="name">将要添加的属性名称，不可为 Null。</param>
        /// <param name="value">将要添加的属性值。</param>
        /// <exception cref="System.ArgumentException"></exception>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetProperty(string name, Json value)
        {
            if (_jobject == null || TokenType != JTokenType.Object)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (name == null)
            {
                if (_throw) throw new ArgumentNullException("name", "参数无效。");
                return false;
            }

            var children = _jobject.Children<JProperty>();
            foreach (var child in children)
            {
                if (child.Name == name)
                {
                    _jobject.Remove(name);
                    break;
                }
            }

            if (value == null)
            {
                _jobject.Add(name, null);
            }
            else
            {
                if (value._jtoken == null)
                {
                    _jobject.Add(name, null);
                }
                else
                {
                    _jobject.Add(name, value._jtoken);
                }
            }
            return true;
        }

        #endregion

        #region Array

        /// <summary>获取所有类型为 Value 的子项。</summary>
        public Json[] GetValues()
        {
            var ab = new ArrayBuilder<Json>();
            if (_jarray != null)
            {
                var children = _jarray.Children<JValue>();
                foreach (var child in children)
                {
                    var json = new Json(child);
                    ab.Add(json);
                }
            }
            return ab.Export();
        }

        /// <summary>获取所有类型为 Object 的子项。</summary>
        public Json[] GetObjects()
        {
            var ab = new ArrayBuilder<Json>();
            if (_jarray != null)
            {
                var children = _jarray.Children<JObject>();
                foreach (var child in children)
                {
                    var json = new Json(child);
                    ab.Add(json);
                }
            }
            return ab.Export();
        }

        /// <summary>获取 Array 中的所有元素。</summary>
        public Json[] GetItems()
        {
            var ab = new ArrayBuilder<Json>();
            if (_jarray != null)
            {
                var children = _jarray.Children();
                foreach (var child in children)
                {
                    var json = new Json(child);
                    ab.Add(json);
                }
            }
            return ab.Export();
        }

        /// <summary>当前实例类型为 Array 时添加 Null 元素。</summary>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool AddItem()
        {
            if (_jarray == null || TokenType != JTokenType.Array)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
                return false;
            }

            _jarray.Add(JValue.CreateNull());
            return true;
        }

        /// <summary>当前实例类型为 Array 时添加元素。</summary>
        /// <param name="json">将要添加的元素。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool AddItem(Json json)
        {
            if (json == null)
            {
                return AddItem();
            }

            if (_jarray == null || TokenType != JTokenType.Array)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
                return false;
            }

            if (json._jtoken == null || json.TokenType == JTokenType.None)
            {
                if (_throw) throw new ArgumentException("json", "将要设置的元素无效。");
                return false;
            }

            _jarray.Add(json._jtoken);
            return true;
        }

        /// <summary>当前实例类型为 Array 时添加元素。</summary>
        /// <param name="value">将要添加的元素。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool AddItem(string value)
        {
            if (_jarray == null || TokenType != JTokenType.Array)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
                return false;
            }

            _jarray.Add(value ?? "");
            return true;
        }

        /// <summary>当前实例类型为 Array 时添加元素。</summary>
        /// <param name="value">将要添加的元素。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool AddItem(bool value)
        {
            if (_jarray == null || TokenType != JTokenType.Array)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
                return false;
            }

            _jarray.Add(value);
            return true;
        }

        /// <summary>当前实例类型为 Array 时添加元素。</summary>
        /// <param name="value">将要添加的元素。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool AddItem(int value)
        {
            if (_jarray == null || TokenType != JTokenType.Array)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
                return false;
            }

            _jarray.Add(value);
            return true;
        }

        /// <summary>当前实例类型为 Array 时添加元素。</summary>
        /// <param name="value">将要添加的元素。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool AddItem(long value)
        {
            if (_jarray == null || TokenType != JTokenType.Array)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
                return false;
            }

            _jarray.Add(value);
            return true;
        }

        /// <summary>当前实例类型为 Array 时添加元素。</summary>
        /// <param name="value">将要添加的元素。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool AddItem(float value)
        {
            if (_jarray == null || TokenType != JTokenType.Array)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
                return false;
            }

            _jarray.Add(value);
            return true;
        }

        /// <summary>当前实例类型为 Array 时添加元素。</summary>
        /// <param name="value">将要添加的元素。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool AddItem(double value)
        {
            if (_jarray == null || TokenType != JTokenType.Array)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
                return false;
            }

            _jarray.Add(value);
            return true;
        }

        /// <summary>当前实例类型为 Array 时添加元素。</summary>
        /// <param name="value">将要添加的元素。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool AddItem(decimal value)
        {
            if (_jarray == null || TokenType != JTokenType.Array)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
                return false;
            }

            _jarray.Add(value);
            return true;
        }

        /// <summary>从 Parent 中移除。</summary>
        /// <exception cref="System.InvalidOperationException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public bool Remove()
        {
            if (_jtoken == null) return false;

            if (_jtoken.Parent == null)
            {
                if (_throw) throw new InvalidOperationException("Parent 对象丢失。");
                return false;
            }

            try
            {
                _jtoken.Remove();
                return true;
            }
            catch (Exception exception)
            {
                if (_throw) throw exception;
                return false;
            }
        }

        /// <summary>获取数组的元素。</summary>
        /// <exception cref="ArgumentOutOfRangeException" />
        /// <exception cref="InvalidOperationException" />
        public object GetItem(int index)
        {
            if (!IsArray) throw new InvalidOperationException(IsNotJsonArray);

            if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), IndexLessZero);
            var jarray = _jtoken as JArray;
            if (index >= jarray.Count) throw new ArgumentOutOfRangeException(nameof(index), IndexGraterCount);

            var item = jarray[index];
            return ParseJToken(item);
        }

        /// <summary>设置数组的元素。</summary>
        /// <exception cref="ArgumentException" />
        /// <exception cref="ArgumentOutOfRangeException" />
        /// <exception cref="InvalidOperationException" />
        public void SetItem(int index, object value)
        {
            if (!IsArray) throw new InvalidOperationException(IsNotJsonArray);

            if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), IndexLessZero);
            var jarray = _jtoken as JArray;
            while (jarray.Count < index + 1) jarray.Add(null);

            var jtoken = ToJToken(value);
            jarray.SetItem(index, jtoken);
        }

        #endregion

        #region Property

        /// <summary>Json 对象实例为空。</summary>
        public bool IsNone { get { return TokenType == JTokenType.None; } }

        /// <summary>Json 对象为 Object 实例。</summary>
        public bool IsObject { get { return TokenType == JTokenType.Object; } }

        /// <summary>Json 对象为 Array 实例。</summary>
        public bool IsArray { get { return TokenType == JTokenType.Array; } }

        /// <summary>Json 对象为 Property 实例。</summary>
        public bool IsProperty { get { return TokenType == JTokenType.Property; } }

        /// <summary>Json 对象为 String 实例。</summary>
        public bool IsString { get { return TokenType == JTokenType.String; } }

        /// <summary>当前实例类型为 Property 时设置 Null 值。</summary>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetValue()
        {
            var available = _jproperty != null && TokenType == JTokenType.Property;
            if (!available)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            _jproperty.Value = JValue.CreateNull();
            return true;
        }

        /// <summary>当前实例类型为 Property 时设置值。</summary>
        /// <param name="value">将要设置的值。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetValue(Json value)
        {
            var available = _jproperty != null && TokenType == JTokenType.Property;
            if (!available)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            if (value == null)
            {
                _jproperty.Value = JValue.CreateNull();
                return true;
            }

            if (value._jtoken == null || value.TokenType == JTokenType.None)
            {
                _jproperty.Value = JValue.CreateNull();
                return true;
            }

            _jproperty.Value = new JValue(value._jtoken);
            return true;
        }

        /// <summary>当前实例类型为 Property 时设置值。</summary>
        /// <param name="value">将要设置的值。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetValue(string value)
        {
            var available = _jproperty != null && TokenType == JTokenType.Property;
            if (!available)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            _jproperty.Value = value == null ? JValue.CreateNull() : JValue.CreateString(value);
            return true;
        }

        /// <summary>当前实例类型为 Property 时设置值。</summary>
        /// <param name="value">将要设置的值。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetValue(bool value)
        {
            var available = _jproperty != null && TokenType == JTokenType.Property;
            if (!available)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            _jproperty.Value = new JValue(value);
            return true;
        }

        /// <summary>当前实例类型为 Property 时设置值。</summary>
        /// <param name="value">将要设置的值。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetValue(int value)
        {
            var available = _jproperty != null && TokenType == JTokenType.Property;
            if (!available)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            _jproperty.Value = new JValue(value);
            return true;
        }

        /// <summary>当前实例类型为 Property 时设置值。</summary>
        /// <param name="value">将要设置的值。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetValue(long value)
        {
            var available = _jproperty != null && TokenType == JTokenType.Property;
            if (!available)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            _jproperty.Value = new JValue(value);
            return true;
        }

        /// <summary>当前实例类型为 Property 时设置值。</summary>
        /// <param name="value">将要设置的值。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetValue(float value)
        {
            var available = _jproperty != null && TokenType == JTokenType.Property;
            if (!available)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            _jproperty.Value = new JValue(value);
            return true;
        }

        /// <summary>当前实例类型为 Property 时设置值。</summary>
        /// <param name="value">将要设置的值。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetValue(double value)
        {
            var available = _jproperty != null && TokenType == JTokenType.Property;
            if (!available)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            _jproperty.Value = new JValue(value);
            return true;
        }

        /// <summary>当前实例类型为 Property 时设置值。</summary>
        /// <param name="value">将要设置的值。</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool SetValue(decimal value)
        {
            var available = _jproperty != null && TokenType == JTokenType.Property;
            if (!available)
            {
                if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
                return false;
            }

            _jproperty.Value = new JValue(value);
            return true;
        }

        #endregion

        #region Import / Export

        #region String -> Json

        /// <summary>解析文本为 Json 对象，失败时返回 Null。</summary>
        /// <exception cref="System.Exception"></exception>
        public static Json From(string text)
        {
            try
            {
                var jtoken = JToken.Parse(text);
                var json = new Json(jtoken);
                return json;
            }
            catch (Exception exception)
            {
                if (AllowException) throw exception;
                return null;
            }
        }

        #endregion

        #region Object -> Json

        /// <summary>解析实现 IList 的对象为 Json 对象，失败时返回 Null。</summary>
        /// <param name="entity">将要解析的对象。</param>
        /// <param name="lower">在 Json 中将属性名称转换为小写。</param>
        /// <param name="depth">限制 Json 层级深度，当值小于零时将不限制深度。</param>
        /// <param name="force">强制解析属性，忽略 Serializable 特性。</param>
        public static Json From(IList entity, bool lower = false, int depth = -1, bool force = false)
        {
            if (entity == null) return null;
            var recursive = new object[] { entity };
            return From(entity, lower, recursive, depth, force);
        }

        /// <summary>解析实现 IDictionary 的对象为 Json 对象，失败时返回 Null。</summary>
        /// <param name="entity">将要解析的对象。</param>
        /// <param name="lower">在 Json 中将属性名称转换为小写。</param>
        /// <param name="depth">限制 Json 层级深度，当值小于零时将不限制深度。</param>
        /// <param name="force">强制解析属性，忽略 Serializable 特性。</param>
        public static Json From(IDictionary entity, bool lower = false, int depth = -1, bool force = false)
        {
            if (entity == null) return null;
            var recursive = new object[] { entity };
            return From(entity, lower, recursive, depth, force);
        }

        /// <summary>
        /// <para>解析对象为 Json 对象，包含所有公共属性，失败时返回 Null。</para>
        /// <para>String 对象将解析文本；Json 对象将返回实例；String 对象将解析文本；实现 IDictionary 或 IList 的对象将解析内容。</para>
        /// </summary>
        /// <param name="entity">将要解析的对象。</param>
        /// <param name="lower">在 Json 中将属性名称转换为小写。</param>
        /// <param name="depth">限制 Json 层级深度，当值小于零时将不限制深度。</param>
        /// <param name="force">强制解析属性，忽略 Serializable 特性。</param>
        /// <exception cref="System.Exception"></exception>
        public static Json From(object entity, bool lower = false, int depth = -1, bool force = false)
        {
            if (entity == null) return null;
            var recursive = new object[] { entity };
            return From(entity, lower, recursive, depth, force);
        }

        private static Json From(IList list, bool lower, object[] previous, int depth, bool force)
        {
            if (list == null) return null;
            if (list is IToJson) return ((IToJson)list).ToJson();

            var checker = list as IToJsonChecker;
            var json = NewArray();
            try
            {
                if (list is Array array)
                {
                    if (array != null && array.Rank > 1)
                    {
                        ToJson(json, array, array.Rank, new int[0]);
                        return json;
                    }
                }

                foreach (var item in list)
                {
                    // 由 IToJsonChecker 实现的方法检查是否包含元素。
                    if (checker != null && !checker.WithItemInJson(list, item)) continue;

                    var value = item;

                    // 检查递归引用。
                    var recursively = false;
                    foreach (var r in previous)
                    {
                        if (ReferenceEquals(r, value))
                        {
                            if (AllowRecursively) json.AddItem();
                            recursively = true;
                            break;
                        }
                    }
                    if (recursively) continue;

                    // value 是 null。
                    if (value.IsNull())
                    {
                        json.AddItem();
                        continue;
                    }

                    // 处理 Type 对象。
                    if (value.GetType().Equals(typeof(Type)) && (previous.Length > 2)) value = FullName((Type)value);

                    // 处理 Assembly 对象。
                    if (value.GetType().Equals(typeof(Assembly)) && (previous.Length > 2)) value = ((Assembly)value).FullName;

                    if (value == null) { json.AddItem(); }
                    else if (value is DateTime dt) { json.AddItem(SerializeDateTime(dt)); }
                    else if (value is bool) { json.AddItem((bool)value); }
                    else if (value is byte) { json.AddItem((byte)value); }
                    else if (value is sbyte) { json.AddItem((sbyte)value); }
                    else if (value is short) { json.AddItem((short)value); }
                    else if (value is ushort) { json.AddItem((ushort)value); }
                    else if (value is int) { json.AddItem((int)value); }
                    else if (value is uint) { json.AddItem((uint)value); }
                    else if (value is long) { json.AddItem((long)value); }
                    else if (value is ulong) { json.AddItem(value.ToString()); }
                    else if (value is float) { json.AddItem((float)value); }
                    else if (value is double) { json.AddItem((double)value); }
                    else if (value is decimal) { json.AddItem((decimal)value); }
                    else if (value is string) { json.AddItem((string)value); }
                    else if (value is Json) { json.AddItem(value as Json); }
                    else
                    {
                        if ((depth < 0) || (0 < depth && previous.Length < depth))
                        {
                            var recursive = new ArrayBuilder<object>(16);
                            recursive.Add(previous);
                            recursive.Add(value);

                            if (value is IDictionary<string, object> asExpando)
                            {
                                var expando = new Dictionary<string, object>(asExpando);
                                json.AddItem(From(expando, lower, recursive, depth, force));
                            }
                            else if (value is IDictionary) { json.AddItem(From(value as IDictionary, lower, recursive, depth, force)); }
                            else if (value is IList) { json.AddItem(From(value as IList, lower, recursive, depth, force)); }
                            else { json.AddItem(From(value, lower, recursive, depth, force)); }
                        }
                        else
                        {
                            json.AddItem(value.ToString());
                        }
                    }
                }
            }
            catch { }
            return json;
        }

        private static Json From(IDictionary dictionary, bool lower, object[] previous, int depth, bool force)
        {
            if (dictionary == null) return null;
            if (dictionary is IToJson) return ((IToJson)dictionary).ToJson();
            // IDictionary 不再需要 SerializableAttribute 特性。
            // {
            //     var dtype = dictionary.GetType();
            //     var sas = dtype.GetCustomAttributes(typeof(SerializableAttribute), false);
            //     if (sas == null || sas.Length < 1) return null;
            // }

            var checker = dictionary as IToJsonChecker;
            var json = NewObject();
            try
            {
                var keys = dictionary.Keys;
                foreach (var key in keys)
                {
                    if (key == null) continue;
                    try
                    {
                        var field = key.ToString() ?? "";
                        if (lower && !string.IsNullOrEmpty(field)) field = field.ToLower();

                        var value = dictionary[key];

                        // 检查递归引用。           
                        var recursively = false;
                        foreach (var r in previous)
                        {
                            if (ReferenceEquals(r, value))
                            {
                                if (AllowRecursively) json.SetProperty(field);
                                recursively = true;
                                break;
                            }
                        }
                        if (recursively) continue;

                        // 检查 System.Attribute.TypeId。
                        if (field == "TypeId" || field == "typeid")
                        {
                            if ((value != null) && (value is Type))
                            {
                                json.SetProperty(field, FullName((Type)value));
                                continue;
                            }
                        }

                        // 由 IToJsonChecker 实现的方法检查是否包含元素。
                        if (checker != null && !checker.WithPropertyInJson(dictionary, field, value)) continue;

                        if (value != null)
                        {
                            // 处理 Type 对象。
                            if (value.GetType().Equals(typeof(Type)) && (previous.Length > 2))
                            {
                                value = FullName((Type)value);
                            }

                            // 处理 Assembly 对象。
                            if (value.GetType().Equals(typeof(Assembly)) && (previous.Length > 2))
                            {
                                value = ((Assembly)value).FullName;
                            }
                        }

                        if (value == null) { json.SetProperty(field); }
                        else if (value is DateTime dt) { json.SetProperty(field, SerializeDateTime(dt)); }
                        else if (value is bool) { json.SetProperty(field, (bool)value); }
                        else if (value is byte) { json.SetProperty(field, (byte)value); }
                        else if (value is sbyte) { json.SetProperty(field, (sbyte)value); }
                        else if (value is short) { json.SetProperty(field, (short)value); }
                        else if (value is ushort) { json.SetProperty(field, (ushort)value); }
                        else if (value is int) { json.SetProperty(field, (int)value); }
                        else if (value is uint) { json.SetProperty(field, (uint)value); }
                        else if (value is long) { json.SetProperty(field, (long)value); }
                        else if (value is ulong) { json.SetProperty(field, value.ToString()); }
                        else if (value is float) { json.SetProperty(field, (float)value); }
                        else if (value is double) { json.SetProperty(field, (double)value); }
                        else if (value is decimal) { json.SetProperty(field, (decimal)value); }
                        else if (value is string) { json.SetProperty(field, (string)value); }
                        else if (value is Json) { json.SetProperty(field, value as Json); }
                        else
                        {
                            if ((depth < 0) || (0 < depth && previous.Length < depth))
                            {
                                var recursive = new ArrayBuilder<object>(16);
                                recursive.Add(previous);
                                recursive.Add(value);

                                if (value is IDictionary) { json.SetProperty(field, From(value as IDictionary, lower, recursive, depth, force)); }
                                else if (value is IList) { json.SetProperty(field, From(value as IList, lower, recursive, depth, force)); }
                                else { json.SetProperty(field, From(value, lower, recursive, depth, force)); }
                            }
                            else
                            {
                                json.SetProperty(field, value.ToString());
                            }
                        }
                    }
                    catch { }
                }
            }
            catch { }
            return json;
        }

        private static Json From(object entity, bool lower, object[] previous, int depth, bool force)
        {
            if (entity == null) return null;
            if (entity is IToJson) return ((IToJson)entity).ToJson();
            if (entity is string) return From(entity as string);

            // 递归检查。
            var pab = new ArrayBuilder<object>(16);
            if (previous != null) pab.Add(previous as IEnumerable<object>);
            pab.Add(entity);
            var end = depth > 0 && pab.Count >= depth;

            // 不可递归类型：类型。
            if (entity is Type)
            {

                var t = entity as Type;
                if (t.Equals(typeof(void))) return null;
                var tJson = NewObject();
                if (end) tJson.SetProperty(lower ? "name" : "Name", FullName(t));
                else
                {
                    tJson.SetProperty(lower ? "name" : "Name", t.Name);
                    if (t.IsGenericType)
                    {
                        tJson.SetProperty(lower ? "generic" : "Generic", From(t.GetGenericArguments(), lower, pab, 2, true));
                    }
                    tJson.SetProperty(lower ? "namespace" : "Namespace", t.Namespace);
                }
                tJson.SetProperty(lower ? "assembly" : "Assembly", t.Assembly.Location);

                if (end)
                {
                    tJson.SetProperty(lower ? "properties" : "Properties", t.GetProperties().Length);
                    tJson.SetProperty(lower ? "methods" : "Methods", t.GetMethods().Length);
                }
                else
                {
                    tJson.SetProperty(lower ? "properties" : "Properties", From(t.GetProperties(), lower, new object[0], 1, true));
                    tJson.SetProperty(lower ? "methods" : "Methods", From(t.GetMethods(), lower, new object[0], 1, true));
                }
                return tJson;
            }

            // 不可递归类型：方法。
            if (entity is MethodBase)
            {
                var mb = entity as MethodBase;
                var mbJson = NewObject();
                mbJson.SetProperty(lower ? "name" : "Name", mb.Name);
                mbJson.SetProperty(lower ? "declaring" : "Declaring", FullName(mb.DeclaringType));
                if (mb.IsStatic) mbJson.SetProperty(lower ? "static" : "Static", mb.IsStatic);
                if (mb is MethodInfo mi)
                {
                    mbJson.SetProperty(lower ? "type" : "Type", FullName(mi.ReturnType));
                }
                mbJson.SetProperty(lower ? "parameters" : "Parameters", mb.GetParameters().Length);
                return mbJson;
            }

            // 不可递归类型：成员。
            if (entity is MemberInfo)
            {
                var mi = entity as MemberInfo;
                var miJson = NewObject();
                miJson.SetProperty(lower ? "name" : "Name", mi.Name);
                miJson.SetProperty(lower ? "declaring" : "Declaring", FullName(mi.DeclaringType));

                miJson.SetProperty(lower ? "type" : "Type", mi.MemberType.ToString());

                if (mi is PropertyInfo pi)
                {
                    var getter = pi.GetGetMethod();
                    var setter = pi.GetSetMethod();
                    var isStatic = (getter != null && getter.IsStatic) || (setter != null && setter.IsStatic);
                    if (isStatic) miJson.SetProperty(lower ? "static" : "Static", isStatic);
                    miJson.SetProperty(lower ? "get" : "Get", getter != null);
                    miJson.SetProperty(lower ? "set" : "Set", setter != null);
                }
                else if (mi is FieldInfo fi)
                {
                    if (fi.IsStatic) miJson.SetProperty(lower ? "static" : "Static", true);
                }
                return miJson;
            }

            // 不可递归类型：参数。
            if (entity is ParameterInfo)
            {
                var pi = entity as ParameterInfo;
                var piJson = NewObject();
                piJson.SetProperty(lower ? "name" : "Name", pi.Name);
                piJson.SetProperty(lower ? "type" : "Type", FullName(pi.ParameterType));
                return piJson;
            }

            // 强制序列化。
            var exception = entity as Exception;
            if (exception != null) force = true;
            if (!(force || _forceall) && !CanSerialize(entity.GetType(), false)) return null;

            if (entity is Json) { if (lower) Lower(entity as Json); return entity as Json; }
            else if (entity is String) { return From((string)entity); }
            else if (entity is IDictionary<string, object> asExpando) { return From(new Dictionary<string, object>(asExpando), lower, depth, force); }
            else if (entity is IDictionary) { return From(entity as IDictionary, lower, depth, force); }
            else if (entity is IList) { return From(entity as IList, lower, depth, force); }
            else if (entity is NameValueCollection nc) { return From(CollectionUtility.Dictionary(nc), lower, depth, force); }

            var type = entity.GetType();
            var independent = RuntimeUtility.Contains<IndependentAttribute>(type);
            var checker = entity as IToJsonChecker;
            var properties = type.GetProperties();
            if (properties.LongLength > 0L)
            {
                var dict = new Dictionary<string, object>();

                // 添加异常类型，并提前加入基类属性。
                if (exception != null)
                {
                    dict.Add(lower ? "type" : "Type", FullName(exception.GetType()));
                    dict.Add(lower ? "message" : "Message", Message(exception));

                    var exData = exception.Data;
                    if (exData != null && exData.Count > 0) dict.Add(lower ? "data" : "Data", exData);

                    var exHelpLink = exception.HelpLink;
                    if (!string.IsNullOrEmpty(exHelpLink)) dict.Add(lower ? "help" : "Help", exHelpLink);

                    if (!end)
                    {
                        var stackJson = NewArray();
                        var stackJsonLength = 0;
                        var stackText = exception.StackTrace;
                        if (!string.IsNullOrEmpty(stackText))
                        {
                            var stackSplit = exception.StackTrace.Split('\r', '\n');
                            foreach (var stackItem in stackSplit)
                            {
                                if (string.IsNullOrEmpty(stackItem)) continue;
                                var stackTrim = stackItem.Trim();
                                if (string.IsNullOrEmpty(stackTrim)) continue;
                                stackJson.AddItem(stackTrim);
                                stackJsonLength += 1;
                            }
                        }
                        if (stackJsonLength > 0) dict.Add(lower ? "stack" : "Stack", stackJson);

                        var exTargetSite = exception.TargetSite;
                        if (exTargetSite != null) dict.Add(lower ? "target" : "Target", From(exTargetSite, lower, pab, depth, true));
                    }

                    var innerEx = exception.InnerException;
                    if (innerEx != null)
                    {
                        if (end) dict.Add(lower ? "inner" : "InnerException", FullName(innerEx.GetType()));
                        else dict.Add(lower ? "inner" : "InnerException", From(innerEx, lower, pab, depth, true));
                    }
                }

                foreach (var property in properties)
                {
                    var field = property.Name;
                    if (field == null) continue;

                    // 有 Independent 的对象不包含继承属性。
                    if (independent)
                    {
                        if (!property.DeclaringType.Equals(type)) continue;
                    }

                    // 异常不包含基类中的属性。
                    if (exception != null)
                    {
                        if (property.DeclaringType.Equals(typeof(Exception))) continue;
                    }

                    // 处理 Assembly 对象的 DefinedTypes 和 ExportedTypes 属性。
                    if (entity is Assembly)
                    {
                        var assembly = entity as Assembly;
                        if (assembly != null)
                        {
                            if (field == "DefinedTypes" || field == "ExportedTypes")
                            {
                                continue;
                            }
                        }
                    }

                    var getter = property.GetGetMethod(false);
                    if (getter == null) continue;
                    if (getter.IsStatic) continue;

                    var value = null as object;
                    try
                    {
                        value = getter.Invoke((object)entity, null);

                        // 由 IToJsonChecker 实现的方法检查是否包含元素。
                        if (checker != null && !checker.WithPropertyInJson(entity, property, value)) continue;

                        // 处理 Type 对象。
                        if (getter.ReturnType.Equals(typeof(Type)) && (previous.Length > 2))
                        {
                            value = FullName((Type)value);
                        }

                        // 处理 Assembly 对象。
                        if (getter.ReturnType.Equals(typeof(Assembly)) && (previous.Length > 2))
                        {
                            value = ((Assembly)value).FullName;
                        }
                    }
                    catch (Exception ex)
                    {
                        value = ex.Message;
                    }

                    if (!dict.ContainsKey(field)) dict.Add(field, value);
                }
                var json = From(dict, lower, previous, depth, force);
                return json;
            }
            else
            {
                return NewObject();
            }
        }

        private static void ToJson(Json parent, Array array, int rank, int[] indices)
        {
            var dimension = indices.Length;

            var subIndices = new int[dimension + 1];
            if (dimension > 0) indices.CopyTo(subIndices, 0);
            var subLength = array.GetLength(dimension);

            var end = dimension + 1 >= rank;
            if (end)
            {
                var subLinear = new object[subLength];
                for (var i = 0; i < subLength; i++)
                {
                    subIndices[dimension] = i;
                    subLinear[i] = array.GetValue(subIndices);
                }
                var subJson = Json.From(subLinear);
                parent.Reset(subJson);
            }
            else
            {
                for (var i = 0; i < subLength; i++)
                {
                    subIndices[dimension] = i;
                    var subJson = Json.NewArray();
                    ToJson(subJson, array, rank, subIndices);
                    parent.AddItem(subJson);
                }
            }
        }

        #endregion

        #region Json -> String

        /// <summary>导出文本，可指定缩进。若类型为 String，则导出 String 值，忽略缩进。</summary>
        internal static string Export(Json json, bool indented)
        {
            if (json == null) return "";
            if (json._jtoken == null) return "";
            if (json.TokenType == JTokenType.String && json._jvalue != null)
            {
                return json._jvalue.Value.ToString();
            }

            return json._jtoken.ToString(indented ? Formatting.Indented : Formatting.None);
        }

        /// <summary>生成字符串，默认不缩进。若类型为 String，则导出 String 值。</summary>
        public override string ToString() => Export(this, false);

        /// <summary>生成字符串，可指定缩进。若类型为 String，则导出 String 值，忽略缩进。</summary>
        public string ToString(bool indented) => Export(this, indented);

        #endregion

        #region Json -> Object

        /// <summary>填充类型实例，失败时返回 NULL 值。</summary>
        internal static T Object<T>(Json json, bool ignoreCase = true, string ignoreCharacters = null, bool force = false) where T : class, new()
        {
            if (json == null) return null;
            if (json._jtoken == null) return null;
            if (json.TokenType != JTokenType.Object) return null;

            var entity = Object(typeof(T), json, ignoreCase, ignoreCharacters, force);
            return entity == null ? default : (T)entity;
        }

        /// <summary>将 Json 填充到数组列表，失败时返回 NULL 值。</summary>
        internal static TItem[] Array<TItem>(Json json, bool ignoreCase = true, string ignoreCharacters = null, bool force = false)
        {
            if (json == null) return null;
            if (json._jtoken == null) return null;
            if (json.TokenType != JTokenType.Array) return null;

            var instance = Array(typeof(TItem), json, ignoreCase, ignoreCharacters, force);
            var array = (TItem[])instance;
            return array;
        }

        static ConstructorInfo GetDeserializeConstructor(Type type)
        {
            var types = new Type[] { typeof(Json) };
            var independent = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, types, null);
            if (independent == null) independent = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
            return independent;
        }

        /// <summary>创建指定类型的新实例，将 Json 的内容填充到新实例中。</summary>
        public static object Object(Type type, Json json, bool ignoreCase, string ignoreCharacters, bool force)
        {
            // 检查参数。
            if (type == null) throw new ArgumentNullException(nameof(type));
            if (json == null || json._jtoken == null) return null;

            // 类型自己实现反序列化。
            var independent = GetDeserializeConstructor(type);
            if (independent != null) return independent.Invoke(new object[] { json });

            // 是数组。
            if (type.IsArray)
            {
                var itemType = GetTypeOfArrayItem(type);
                return Array(itemType, json, ignoreCase, ignoreCharacters, force);
            }

            // 是列表
            if (typeof(IList).IsAssignableFrom(type))
            {
                var genericTypes = type.GetGenericArguments();
                if (genericTypes != null && genericTypes.Length == 1)
                {
                    var genericType = genericTypes[0];
                    if (genericType != null)
                    {
                        var array = Array(genericType, json, ignoreCase, ignoreCharacters, force);
                        var list = ArrayToList(array, type);
                        return list;
                    }
                }
            }

            // 必须是有效的 Json 实例。
            if (json.TokenType != JTokenType.Object && json.TokenType != JTokenType.Array) return null;

            // 必须有无参数的构造函数。
            var constructor = type.GetConstructor(System.Type.EmptyTypes);
            if (constructor == null) return null;

            // 创建实例。
            var entity = constructor.Invoke(null);

            var jps = json.GetProperties();
            if (jps.Length < 1) return entity;

            var etype = entity.GetType();
            var eps = etype.GetProperties();
            if (eps.Length < 1) return entity;

            foreach (var ep in eps)
            {
                foreach (var jp in jps)
                {
                    var jpn = TextUtility.Trim(jp.Name);
                    var epn = TextUtility.Trim(ep.Name);

                    if (ignoreCharacters != null)
                    {
                        var characters = ignoreCharacters.ToCharArray();
                        foreach (var character in characters)
                        {
                            jpn.Replace(character.ToString(), "");
                            epn.Replace(character.ToString(), "");
                        }
                    }

                    if (ignoreCase)
                    {
                        if (jpn.Length > 0) jpn = jpn.ToLower();
                        if (epn.Length > 0) epn = epn.ToLower();
                    }

                    if (jpn.Length < 1 || epn.Length < 1) continue;
                    if (jpn != epn) continue;

                    var value = jp.Value;
                    if (value == null) continue;

                    Property(entity, ep, value, ignoreCase, ignoreCharacters, force);
                }
            }

            return entity;
        }

        static void Add(object entity, object item, int index)
        {
            try
            {
                if (entity is Array array) array.SetValue(item, index);
                else if (entity is IList list) list.Add(item);
            }
            catch (Exception ex)
            {
                if (_throw) throw ex;
            }
        }

        /// <exception cref="ArgumentNullException" />
        internal static object Array(Type itemType, Json json, bool ignoreCase, string ignoreCharacters, bool force)
        {
            if (itemType == null) throw new ArgumentNullException(nameof(itemType));
            if (json == null) return null;

            // 必须是有效的 Json 实例。
            if (json.TokenType != JTokenType.Array) return null;

            // 加入列表。
            var items = json.GetItems();
            var list = new List<object>(items.Length);
            for (var index = 0; index < items.Length; index++)
            {
                var item = items[index];
                if (item == null) list.Add(null);
                else if (itemType.Equals(typeof(Json))) list.Add(item);
                else if (itemType.Equals(typeof(string))) list.Add(item ? item.Text : null);
                else if (itemType.Equals(typeof(byte))) list.Add(Byte(item.Text));
                else if (itemType.Equals(typeof(short))) list.Add(Int16(item.Text));
                else if (itemType.Equals(typeof(int))) list.Add(Int32(item.Text));
                else if (itemType.Equals(typeof(long))) list.Add(Int64(item.Text));
                else if (itemType.Equals(typeof(sbyte))) list.Add(SByte(item.Text));
                else if (itemType.Equals(typeof(ushort))) list.Add(UInt16(item.Text));
                else if (itemType.Equals(typeof(uint))) list.Add(UInt32(item.Text));
                else if (itemType.Equals(typeof(ulong))) list.Add(UInt64(item.Text));
                else if (itemType.Equals(typeof(float))) list.Add(Single(item.Text));
                else if (itemType.Equals(typeof(double))) list.Add(Double(item.Text));
                else if (itemType.Equals(typeof(decimal))) list.Add(Decimal(item.Text));
                else
                {
                    var serializable = (force || _forceall) ? true : CanSerialize(itemType, false);
                    if (serializable)
                    {
                        var itemInstance = Object(itemType, item, ignoreCase, ignoreCharacters, force);
                        list.Add(itemInstance);
                    }
                    else
                    {
                        list.Add(null);
                    }
                }
            }

            // 输出数组。
            var array = System.Array.CreateInstance(itemType, list.Count);
            for (var i = 0; i < list.Count; i++) array.SetValue(list[i], i);
            return array;
        }

        private static void Property(object entity, PropertyInfo property, object value, bool ignoreCase, string ignoreCharacters, bool force)
        {
            if (entity == null) return;
            if (property == null) return;
            if (value == null) return;

            var setter = property.GetSetMethod();
            if (setter == null) return;

            var pt = property.PropertyType;
            var ptname = FullName(property.PropertyType);

            if (ptname == FullName(typeof(Json)))
            {
                if (value is Json) setter.Invoke(entity, new object[] { value });
            }
            else
            {
                if (pt.Equals(typeof(DateTime)))
                {
                    if (AllowException)
                    {
                        setter.Invoke(entity, new object[] { DeserializeDateTime(value) });
                    }
                    else
                    {
                        try
                        {
                            setter.Invoke(entity, new object[] { DeserializeDateTime(value) });
                        }
                        catch { }
                    }
                }
                else if (pt.Equals(typeof(string)))
                {
                    if (value is Json asJson) setter.Invoke(entity, new object[] { ((Json)value).TokenType == JTokenType.Null ? null : ((Json)value).Text });
                    else setter.Invoke(entity, new object[] { value.ToString() });
                }
                else if (pt.Equals(typeof(bool))) setter.Invoke(entity, new object[] { Boolean(value) });
                else if (pt.Equals(typeof(byte))) setter.Invoke(entity, new object[] { Byte(value) });
                else if (pt.Equals(typeof(sbyte))) setter.Invoke(entity, new object[] { SByte(value) });
                else if (pt.Equals(typeof(short))) setter.Invoke(entity, new object[] { Int16(value) });
                else if (pt.Equals(typeof(ushort))) setter.Invoke(entity, new object[] { UInt16(value) });
                else if (pt.Equals(typeof(int))) setter.Invoke(entity, new object[] { Int32(value) });
                else if (pt.Equals(typeof(uint))) setter.Invoke(entity, new object[] { UInt32(value) });
                else if (pt.Equals(typeof(long))) setter.Invoke(entity, new object[] { Int64(value) });
                else if (pt.Equals(typeof(ulong))) setter.Invoke(entity, new object[] { UInt64(value) });
                else if (pt.Equals(typeof(float))) setter.Invoke(entity, new object[] { Float(value) });
                else if (pt.Equals(typeof(double))) setter.Invoke(entity, new object[] { Double(value) });
                else if (pt.Equals(typeof(decimal))) setter.Invoke(entity, new object[] { Decimal(value) });
                else
                {
                    var serializable = (force || _forceall);
                    if (!serializable) serializable = CanSerialize(property.PropertyType, false);
                    if (serializable && value is Json json)
                    {
                        if (pt.IsArray)
                        {
                            var array = Array(pt.GetElementType(), json, ignoreCase, ignoreCharacters, force);
                            setter.Invoke(entity, array);
                        }
                        else if (typeof(IList).IsAssignableFrom(pt))
                        {
                            var genericTypes = pt.GetGenericArguments();
                            if (genericTypes != null && genericTypes.Length == 1)
                            {
                                var genericType = genericTypes[0];
                                if (genericType != null)
                                {
                                    var array = Array(genericType, json, ignoreCase, ignoreCharacters, force);
                                    var list = ArrayToList(array, pt);
                                    setter.Invoke(entity, list);
                                }
                            }
                        }
                        else
                        {
                            var @object = Object(pt, json, ignoreCase, ignoreCharacters, force);
                            setter.Invoke(entity, @object);
                        }
                    }
                }
            }
        }

        static IList ArrayToList(object array, Type listType)
        {
            if (listType == null) throw new ArgumentNullException(nameof(listType));

            if (array != null && array is Array a)
            {
                var list = Activator.CreateInstance(listType) as IList;
                for (var i = 0; i < a.Length; i++) list.Add(a.GetValue(i));
                return list;
            }

            return null;
        }

        #endregion

        #endregion

        #region Dynamic

#if !NET20

        /// <summary></summary>
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (!IsObject) throw new InvalidOperationException(IsNotJsonObject);

            var contains = _jobject.ContainsKey(binder.Name);
            if (!contains)
            {
                result = null;
                return true;
            }

            var jtoken = _jobject.GetValue(binder.Name);
            result = ParseJToken(jtoken);
            return true;
        }

        /// <summary></summary>
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (!IsObject) throw new InvalidOperationException(IsNotJsonObject);

            var contains = _jobject.ContainsKey(binder.Name);
            if (contains)
            {
                _jobject[binder.Name] = ToJToken(value);
                return true;
            }
            else
            {
                _jobject.Add(binder.Name, ToJToken(value));
                return true;
            }
        }

        private Class<T> DynamicIndex<T>(object[] indexes, Func<string, T> stringCallback, Func<int, T> intCallback)
        {
            var index = indexes[0];
            if (index != null)
            {
                if (IsObject)
                {
                    if (index is string name) return new Class<T>(stringCallback.Invoke(name));
                }
                if (IsArray)
                {
                    if (index is int || index is short || index is byte || index is ushort || index is sbyte)
                    {
                        var int32 = int.Parse(index.ToString());
                        if (int32 < 0) throw new ArgumentOutOfRangeException("index", IndexLessZero);
                        return new Class<T>(intCallback(int32));
                    }
                    else if (index is long int64)
                    {
                        if (int64 < 0) throw new ArgumentOutOfRangeException("index", IndexLessZero);
                        if (int64 > int.MaxValue) throw new ArgumentOutOfRangeException("index", IndexGraterMax);
                        var int32 = Convert.ToInt32(int64);
                        return new Class<T>(intCallback(int32));
                    }
                    else if (index is uint uint32)
                    {
                        if (uint32 > int.MaxValue) throw new ArgumentOutOfRangeException("index", IndexGraterMax);
                        var int32 = Convert.ToInt32(uint32);
                        return new Class<T>(intCallback(int32));
                    }
                    else if (index is ulong uint64)
                    {
                        if (uint64 > int.MaxValue) throw new ArgumentOutOfRangeException("index", IndexGraterMax);
                        var int32 = Convert.ToInt32(uint64);
                        return new Class<T>(intCallback(int32));
                    }
                }
            }

            throw new InvalidOperationException(InvalidIndex);
        }

        /// <summary></summary>
        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
        {
            var box = DynamicIndex(indexes, name =>
            {
                var property = GetProperty(name);
                return ParseJToken(property?._jtoken);
            }, index =>
            {
                return GetItem(index);
            });
            if (box == null)
            {
                result = null;
                return false;
            }
            else
            {
                result = box.Value;
                return true;
            }
        }

        /// <summary></summary>
        public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
        {
            var box = DynamicIndex(indexes, name =>
            {
                _jobject[name] = ToJToken(value);
                return true;
            }, index =>
            {
                SetItem(index, value);
                return true;
            });

            return box != null;
        }

        /// <summary></summary>
        public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
        {
            switch (binder.CallInfo.ArgumentNames.First().Lower())
            {
                case "tostring":
                    if (args == null)
                    {
                        result = ToString();
                        return true;
                    }
                    else
                    {
                        switch (args.Length)
                        {
                            case 0:
                                result = ToString();
                                return true;
                            case 1:
                                if (args[0] == null)
                                {
                                    result = null;
                                    return false;
                                }
                                else
                                {
                                    if (args[0] is bool indented)
                                    {
                                        result = ToString(indented);
                                        return true;
                                    }
                                    else if (args[0] is byte int8)
                                    {
                                        result = ToString(int8 == 1);
                                        return true;
                                    }
                                    else if (args[0] is short int16)
                                    {
                                        result = ToString(int16 == 1);
                                        return true;
                                    }
                                    else if (args[0] is int int32)
                                    {
                                        result = ToString(int32 == 1);
                                        return true;
                                    }
                                    else if (args[0] is long int64)
                                    {
                                        result = ToString(int64 == 1);
                                        return true;
                                    }
                                    else
                                    {
                                        result = null;
                                        return false;
                                    }
                                }
                            default:
                                result = null;
                                return false;
                        }
                    }
                default:
                    result = null;
                    return false;
            }
        }

        /// <summary></summary>
        public override bool TryConvert(ConvertBinder binder, out object result)
        {
            if (binder.Type.Equals(typeof(Json)))
            {
                result = this;
                return true;
            }
            if (binder.Type.Equals(typeof(string)))
            {
                result = ToString();
                return true;
            }

            result = null;
            return false;
        }

#endif

        #endregion

        #region 运算符。

        /// <summary>从 Json 到 Boolean 的隐式转换，判断 Json 对象可用。</summary>
        public static implicit operator bool(Json json) => json != null && json.Available;

        /// <summary>从 Json 到 String 的隐式转换，默认不缩进。</summary>
        public static implicit operator string(Json json) => Export(json, false);

        /// <summary>从 String 到 Json 的隐式转换。</summary>
        /// <exception cref="System.Exception"></exception>
        public static implicit operator Json(string text) => From(text);

        #endregion

        #region Statics

        #region 创建实例。

        /// <summary>创建新对象。</summary>
        public static Json NewObject()
        {
            return new Json(new JObject());
        }

        /// <summary>创建新对象。</summary>
        public static Json NewObject(Dictionary<string, string> dictionary)
        {
            var json = new Json(null);
            json.Reset(dictionary);
            return json;
        }

        /// <summary>创建新对象。</summary>
        public static Json NewObject(TextSet dictionary)
        {
            var json = new Json(null);
            json.Reset(dictionary);
            return json;
        }

        /// <summary>创建新对象。</summary>
        public static Json NewObject(ObjectSet<string> dictionary)
        {
            var json = new Json(null);
            json.Reset(dictionary);
            return json;
        }

        /// <summary>创建新对象。</summary>
        public static Json NewArray()
        {
            return new Json(new JArray());
        }

        /// <summary>新建类型为 Property 的实例，值为 Null，失败时返回 Null。</summary>
        /// <param name="name">Property 名称，不可为 Null。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static Json NewProperty(string name)
        {
            if (name == null)
            {
                if (AllowException) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }
            return new Json(new JProperty(name, null));
        }

        /// <summary>新建类型为 Property 的实例，失败时返回 Null。</summary>
        /// <param name="name">Property 名称，不可为 Null。</param>
        /// <param name="value">Property 值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static Json NewProperty(string name, string value)
        {
            if (name == null)
            {
                if (AllowException) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }
            return new Json(new JProperty(name, value));
        }

        /// <summary>新建类型为 Property 的实例，失败时返回 Null。</summary>
        /// <param name="name">Property 名称，不可为 Null。</param>
        /// <param name="value">Property 值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static Json NewProperty(string name, bool value)
        {
            if (name == null)
            {
                if (AllowException) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }
            return new Json(new JProperty(name, value));
        }

        /// <summary>新建类型为 Property 的实例，失败时返回 Null。</summary>
        /// <param name="name">Property 名称，不可为 Null。</param>
        /// <param name="value">Property 值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static Json NewProperty(string name, int value)
        {
            if (name == null)
            {
                if (AllowException) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }
            return new Json(new JProperty(name, value));
        }

        /// <summary>新建类型为 Property 的实例，失败时返回 Null。</summary>
        /// <param name="name">Property 名称，不可为 Null。</param>
        /// <param name="value">Property 值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static Json NewProperty(string name, long value)
        {
            if (name == null)
            {
                if (AllowException) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }
            return new Json(new JProperty(name, value));
        }

        /// <summary>新建类型为 Property 的实例，失败时返回 Null。</summary>
        /// <param name="name">Property 名称，不可为 Null。</param>
        /// <param name="value">Property 值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static Json NewProperty(string name, float value)
        {
            if (name == null)
            {
                if (AllowException) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }
            return new Json(new JProperty(name, value));
        }

        /// <summary>新建类型为 Property 的实例，失败时返回 Null。</summary>
        /// <param name="name">Property 名称，不可为 Null。</param>
        /// <param name="value">Property 值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static Json NewProperty(string name, double value)
        {
            if (name == null)
            {
                if (AllowException) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }
            return new Json(new JProperty(name, value));
        }

        /// <summary>新建类型为 Property 的实例，失败时返回 Null。</summary>
        /// <param name="name">Property 名称，不可为 Null。</param>
        /// <param name="value">Property 值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static Json NewProperty(string name, decimal value)
        {
            if (name == null)
            {
                if (AllowException) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }
            return new Json(new JProperty(name, value));
        }

        /// <summary>新建类型为 Property 的实例，失败时返回 Null。</summary>
        /// <param name="name">Property 名称，不可为 Null。</param>
        /// <param name="value">Property 值。</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static Json NewProperty(string name, Json value)
        {
            if (name == null)
            {
                if (AllowException) throw new ArgumentNullException("name", "参数无效。");
                return null;
            }
            if (value == null) return new Json(new JProperty(name, null));
            return new Json(new JProperty(name, null));
        }

        #endregion

        /// <summary>格式化 Json 文本。</summary>
        public static string Format(string text)
        {
            if (text == null || text == "") return "";
            try
            {
                var serializer = new Newtonsoft.Json.JsonSerializer();
                var tr = (System.IO.TextReader)(new System.IO.StringReader(text));
                var jtr = new Newtonsoft.Json.JsonTextReader(tr);
                var obj = serializer.Deserialize(jtr);
                if (obj != null)
                {
                    var textWriter = new System.IO.StringWriter();
                    var jsonWriter = new Newtonsoft.Json.JsonTextWriter(textWriter)
                    {
                        Formatting = Newtonsoft.Json.Formatting.Indented,
                        Indentation = 4,
                        IndentChar = ' '
                    };
                    serializer.Serialize(jsonWriter, obj);
                    return textWriter.ToString();
                }
                else
                {
                    return text;
                }
            }
            catch
            {
                return text ?? "";
            }
        }

        /// <summary>重命名属性名称。</summary>
        public static Json Rename(Json json, Func<string, string> renamer)
        {
            if (json == null) return null;
            switch (json.TokenType)
            {
                case JTokenType.Array:
                    var items = json.GetItems();
                    foreach (var i in items) Rename(i, renamer);
                    break;
                case JTokenType.Object:
                    var properties = json.GetProperties();
                    foreach (var i in properties)
                    {
                        var name = i._jproperty.Name;
                        var value = i._jproperty.Value;

                        if (!string.IsNullOrEmpty(name))
                        {
                            var newName = renamer(name);
                            var newValue = Rename(new Json(value), renamer)?._jtoken;
                            if (name != newName)
                            {
                                i.Remove();
                                json._jobject.Add(newName, newValue ?? value);
                            }
                        }
                    }
                    break;
            }
            return json;
        }

        /// <summary>设置属性名称为小写。</summary>
        public static Json Lower(Json json) => Rename(json, (old) => old.Lower());

        /// <summary>设置属性名称为驼峰形式。</summary>
        public static Json Camel(Json json) => Rename(json, (old) => TextUtility.Camel(old));

        private static bool CanSerialize(Type type, bool inherit = false)
        {
            if (type == null) return false;

            if (type.BaseType.Equals(typeof(Array))) return true;

            var interfaces = type.GetInterfaces();
            foreach (var i in interfaces)
            {
                if (i.Equals(typeof(IList))) return true;
            }

            if (type.Equals(typeof(object))) return false;
            var sas = type.GetCustomAttributes(typeof(SerializableAttribute), inherit);
            if (sas != null && sas.Length > 0) return true;

            var tas = type.GetCustomAttributes(typeof(Source.TableAttribute), inherit);
            if (tas != null && tas.Length > 0) return true;

            return false;
        }

        /// <summary>序列化指定对象为 JSON 字符串。</summary>
        /// <exception cref="Exception"></exception>
        public static string SerializeObject(object @object, Type type = null, bool indented = false, string onError = null) => JsonConvert.SerializeObject(@object, type, indented ? Formatting.Indented : Formatting.None, null);

        /// <summary>反序列化 JSON 字符串为指定的类型。</summary>
        /// <exception cref="Exception"></exception>
        public static T DeserializeObject<T>(string json) => (T)DeserializeObject(json, typeof(T));

        /// <summary>反序列化 JSON 字符串为指定的类型。</summary>
        /// <exception cref="Exception"></exception>
        public static object DeserializeObject(string json, Type type = null) => JsonConvert.DeserializeObject(json, type, (JsonSerializerSettings)null);

#if !NET20

        /// <summary>反序列化 JSON 字符串为指定的类型列表。</summary>
        /// <typeparam name="T">要反序列化的类型。</typeparam>
        /// <param name="json">将要反序列化的 JSON 字符串。</param>
        /// <param name="returnNullOnError">发生错误时返回 NULL 值，设置为 FALSE 时返回空 List&lt;<typeparamref name="T"/>&gt; 对象。</param>
        /// <returns></returns>
        public static T[] DeserializeArray<T>(string json, bool returnNullOnError = false) where T : class
        {
            try
            {
                var serializer = new JsonSerializer();
                var @object = null as object;
                using (var sr = new StringReader(json))
                {
                    using (var jtr = new JsonTextReader(sr))
                    {
                        @object = serializer.Deserialize(jtr, typeof(T[]));
                    }
                }
                return (@object as T[]) ?? new T[0];
            }
            catch { return returnNullOnError ? null : new T[0]; }
        }

#endif

        #endregion

        #region DateTime

        static Func<DateTime, string> _datetime_serializer = null;
        static Func<object, DateTime> _datetime_deserializer = null;

        /// <summary>自定义 DateTime 序列化程序。</summary>
        public static Func<DateTime, string> DateTimeSerializer { get => _datetime_serializer; set => _datetime_serializer = value; }

        /// <summary>自定义 DateTime 反序列化程序。</summary>
        public static Func<object, DateTime> DateTimeDeserializer { get => _datetime_deserializer; set => _datetime_deserializer = value; }

        /// <summary>序列化 DateTime 实例。</summary>
        public static string SerializeDateTime(DateTime dateTime)
        {
            var serializer = _datetime_serializer;
            if (serializer != null) return serializer.Invoke(dateTime);

            return ClockUtility.Lucid(dateTime);
        }

        /// <summary>序列化 DateTime 实例。</summary>
        public static DateTime DeserializeDateTime(object value)
        {
            var deserializer = _datetime_deserializer;
            if (deserializer != null) return deserializer.Invoke(value);

            try
            {
                if (value is DateTime dt) return dt;

                var text = value.ToString();
                var parse = ClockUtility.Parse(text);
                if (parse != null) return parse.Value;
            }
            catch { }
            return default;
        }

        #endregion

    }

}
